<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>

    <body>
        <script>
            // 实现数组响应式
            // 1. 替换数组原型中7个方法
            const originalProto = Array.prototype
            // 克隆体原数组原型
            const arrayProto = Object.create(originalProto)
            // 可修改数组的7个方法 , 'sort'
            const changeMethods = ['push', 'pop', 'shift', 'unshift', 'slice', 'splice', 'sort']
            //  2. 在克隆的原型上，覆盖那些能够修改数组的更新方法，让他们在修改数组同时，还可以通知更新
            changeMethods.forEach(method => {
                arrayProto[method] = function () {
                    // 进行原始操作
                    originalProto[method].apply(this, arguments)
                    // 覆盖操作：增加更新通知
                    console.log(`数组正在执行${method}方法`);
                }
            })
            // 对象响应化
            function defineReactive (obj, key, value) {
                Object.defineProperty(obj, key, {
                    get () {
                        console.log('获取' + key);
                        return value
                    },
                    set (newVal) {
                        if (newVal !== value) {
                            // console.log(newVal);
                            // console.log(JSON.stringify(obj[key]));
                            console.log(`正在改变${key}值: 从${obj[key]}变为${newVal}`)
                            value = newVal
                        }
                    }
                })
            }
            function observer (obj) {
                // 不是对象或者为null，不做响应式，结束
                if (typeof obj !== 'object' || obj === null) return;
                // 如果是数组，修改其实例的原型
                if (Array.isArray(obj)) {
                    // 3. 将得到的新的原型设置到数组实例原型上
                    obj.__proto__ = arrayProto
                    // 4. 对数组内的元素，同样进行响应化
                    for (let i = 0; i < obj.length; i++) {
                        // console.log(obj[i]);
                        observer(obj[i])
                    }
                    // 如果是对象
                } else {
                    Object.keys(obj).forEach(key => {
                        console.log(obj, key, obj[key]);
                        defineReactive(obj, key, obj[key])
                    })
                }
            }
            obj = [{ a: 1 }, 2, 7, 5, 3]
            observer(obj)
            obj.push(4) // 数组正在执行push方法
            obj.pop() // 数组正在执行pop方法
// obj[0].a = 2
//         // 获取a
//         // 正在改变a值:从1变为2
//         obj.sort()  // 数组正在执行sort方法
//         console.log(obj); // [ 2, 3, 5, 7, { a: [Getter/Setter] } ]
//         console.log(obj[4].a);
// // 获取a
// // 2
        </script>
    </body>

    </html>
</body>

</html>